package vip.meeet.util;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.Key;

public class EncryptUtil {

    private static final String ALGORITHM = "PBEWithSHA1AndDESede";

    /**
     * 盐
     */
    private static final byte[] SALT = "PBEAES3DESDES".getBytes();

    /**
     * 迭代次数
     */
    private static final int COUNT = 99;

    /**
     *
     * @param scrfile 待加密文件路径
     * @param destFile 加密之后文件路径
     * @param pass 密码
     * @throws Exception
     */
    public static void encrypt(String scrfile, String destFile,String pass) throws Exception {
        PBEKeySpec pbeKeySpec = new PBEKeySpec(pass.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        Key key = factory.generateSecret(pbeKeySpec);

        PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(SALT, COUNT);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);

        InputStream is = new FileInputStream(scrfile);
        OutputStream out = new FileOutputStream(destFile);
        CipherInputStream cis = new CipherInputStream(is, cipher);
        byte[] buffer = new byte[1024];
        int r;
        while ((r = cis.read(buffer)) > 0) {
            out.write(buffer, 0, r);
        }
        cis.close();
        is.close();
        out.close();
    }

    /**
     *
     * @param content 待加密内容
     * @param destFilePath 加密之后保存文件路径
     * @param pass
     * @throws Exception
     */
    public static void encryptContent(String content, String destFilePath,String pass) throws Exception {
        PBEKeySpec pbeKeySpec = new PBEKeySpec(pass.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        Key key = factory.generateSecret(pbeKeySpec);

        PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(SALT, COUNT);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);

        byte[] bytes = cipher.doFinal(content.getBytes());
        Path path = Paths.get(destFilePath);
        Files.write(path,bytes, StandardOpenOption.CREATE);
    }

    /**
     *
     * @param content 要加密的字符串
     * @param pass 密码
     * @throws Exception
     */
    public static byte[] encrypt(String content,String pass) throws Exception {
        PBEKeySpec pbeKeySpec = new PBEKeySpec(pass.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        Key key = factory.generateSecret(pbeKeySpec);

        PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(SALT, COUNT);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);
        return cipher.doFinal(content.getBytes());
    }

    public static void decrypt(String srcFilePath, String destFilePath, String pass) throws Exception {
        PBEKeySpec pbeKeySpec = new PBEKeySpec(pass.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        Key key = factory.generateSecret(pbeKeySpec);

        PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(SALT, COUNT);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);

        InputStream is = new FileInputStream(srcFilePath);
        OutputStream out = new FileOutputStream(destFilePath);
        CipherOutputStream cos = new CipherOutputStream(out, cipher);
        byte[] buffer = new byte[1024];
        int r;
        while ((r = is.read(buffer)) >= 0) {
            cos.write(buffer, 0, r);
        }
        cos.close();
        out.close();
        is.close();
    }

    /**
     * 获取加密文件内容
     * @param srcFile
     * @param pass
     * @return
     * @throws Exception
     */
    public static String decrypt(File srcFile, String pass) throws Exception {
        PBEKeySpec pbeKeySpec = new PBEKeySpec(pass.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        Key key = factory.generateSecret(pbeKeySpec);

        PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(SALT, COUNT);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);

        InputStream is = new FileInputStream(srcFile);
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) >= 0) {
            byte[] update = cipher.update(buffer, 0, len);
            bao.write(update);
        }
        byte[] bytes = cipher.doFinal();
        if(bytes != null && bytes.length > 0){
            bao.write(bytes);
        }
        is.close();
        return bao.toString();
    }
}
